CS448 - Lab 2: Filter Design and Usage¶

For this lab you will learn how to design some simple filters and how to apply them to solve some common audio problems. Python’s scipy.signal package has an extensive set of commands to help you design filters (firwin, firwin2, butter, cheby1, cheby2, ellip, …), so there is no shortage of options.

Part 1: When to use what¶

There will be four cases to this part, each requiring a different type of filter to address a problem in a recording. The input recordings are:

  • case1.wav [https://drive.google.com/uc?export=download&id=1eTsDiXqqLQv3murPz25O54E89i3DL__d ] : A noise-corrupted speech signal. We want to eliminate the noise.
  • case2.wav [https://drive.google.com/uc?export=download&id=1egd22CxPUe6sINIi0FPTbMfG4S_In2hT ] : Same as above, different type of noise. We want to remove the noise again.
  • case3.wav [https://drive.google.com/uc?export=download&id=1eF-VOVWoT1rh1wAC06WT1ANusMKyDYSn ] : Bird songs during a thunderstorm. As a world renowned ornithologist you need to have a cleaner recording of the bird songs for further analysis.
  • case4.wav [https://drive.google.com/uc?export=download&id=1eeizGhrBICf6pW5OXcbq7ChF4m2N6yIk ]: The signal that we require to extract here is a Morse code which is buried in environmental noise. Design a filter to bring out the beeps.

For each case do the following:

  • Plot the spectrogram of the given sound and identify the problem
  • Describe what kind of filter will address this problem and why
  • Design an FIR filter using scipy.signal.firwin() and/or scipy.signal.firwin2()
  • Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
  • Design an IIR Butterworth filter using scipy.signal's routines
  • Show a plot comparing the response of all the filters (hint: scipy.signal.freqz)
  • Plot spectrograms of the filtered recordings and compare with the input to show that it fixed the problem
  • Play the filtered sounds so that we can hear how well it works

Make some observations on how the results differ between an FIR and IIR filter and try to find the best possible filter size/type/parameters to produce the best result. Show results under various parameters (e.g. filter length) and make some plots that demonstrate the effects of these parameters. Most importantly, try to get a sense of how these design choices impact audible quality. Being able to listen at a sound and identify what’s wrong and how to fix it is a big part of audio processing.

Hint: To apply an FIR filter you can use scipy.signal.convolve, to apply an IIR filter (or an FIR) you can use scipy,signal.lfilter.

In [ ]:
### IMPORTS ###

import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (4, 3)

import numpy as np
from scipy.io import wavfile
from scipy.signal import firwin, firwin2, freqz, lfilter, get_window, butter, convolve
In [ ]:
### UTILITIES ###


# Sound player function that plays array "x" with a sample rate "rate", and labels it with "label"
def sound(x, rate=8000, label=''):
    from IPython.display import display, Audio, HTML
    display(
        HTML('<style> table, th, td {border: 0px; }</style> <table><tr><td>' +
             label + '</td><td>' + Audio(x, rate=rate)._repr_html_()[3:] +
             '</td></tr></table>'))


# Function that normalizes a signal
def normalize_signal(x):
    return x / np.max(np.abs(x))


# Function that plots the spectrogram of a sound
def plot_spectrogram(input_sound, fs, title="Spectrogram"):
    plt.title(title)
    plt.specgram(input_sound, Fs=fs, cmap="winter")
    plt.xlabel('Time [sec]')
    plt.ylabel('Frequency [Hz]')
    plt.show()


# Function that plots the frequency response of a filter
def plot_freq_response(w, h, fs, cutoff, title):
    plt.plot(0.5 * fs * w / np.pi, np.abs(h), 'b')
    plt.axvline(cutoff, color='k', linestyle='--')
    plt.xlim(0, 0.5 * fs)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain')
    plt.title(title)
    plt.grid(True)
    plt.show()


# Function that plots the frequency response of an equalizer
def plot_eq(fs, w, h, title="Frequency response of the equalizer"):
    plt.plot(fs * w / (2 * np.pi), 20 * np.log10(abs(h)))
    plt.title(title)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain (dB)')
    plt.ylim(-50, 10)
    plt.show()
In [ ]:
### FILTERS ###


# Function that creates a firwin low-pass filter
def firwin_low_pass(input, fs, cutoff):
    filter = firwin(5000, cutoff, fs=fs, pass_zero=True)
    w, h = freqz(filter, worN=8000)

    return [convolve(filter, input), w, h]


# Function that creates an FIR low-pass filter
def FIR_low_pass(input, cutoff):
    FIR = cutoff * np.sinc(cutoff * np.arange(-200, 200))
    FIR_windowed = np.multiply(FIR, get_window('hann', 400))

    w, h = freqz(FIR_windowed, worN=8000)
    return [convolve(FIR_windowed, input), w, h]


# Function that creates a butterworth low-pass filter
def butter_low_pass(input, fs, cutoff):
    b, a = butter(12, cutoff / (fs / 2))
    w, h = freqz(b, a)

    return [lfilter(b, a, input), w, h]


# Function that creates a firwin band-reject filter
def firwin_band_reject(input, fs, cutoff):
    filter = firwin(201, cutoff, fs=fs)
    w, h = freqz(filter, worN=8000)

    return [convolve(filter, input), w, h]


# Function that creates an FIR band-reject filter
def FIR_band_reject(input, center, width):
    n = np.arange(-1000, 1000)
    FIR = -2 * np.cos(np.pi * n * center) * width * np.sinc(width * n)
    FIR[int(len(FIR) / 2)] += 1

    FIR_windowed = np.multiply(FIR, get_window('hann', 1000 * 2))
    w, h = freqz(FIR_windowed, worN=8000)
    return [convolve(FIR_windowed, input), w, h]


# Function that creates a butterworth band-reject filter
def butter_band_reject(input, fs, cutoff):
    cutoff = [cutoff[0] / (fs / 2), cutoff[1] / (fs / 2)]
    b, a = butter(12, cutoff, btype='bandstop')
    w, h = freqz(b, a)

    return [lfilter(b, a, input), w, h]


# Function that creates a firwin high-pass filter
def firwin_high_pass(input, fs, cutoff):
    filter = firwin(201, cutoff, fs=fs, pass_zero=False)
    w, h = freqz(filter, worN=8000)

    return [convolve(filter, input), w, h]


# Function that creates an FIR high-pass filter
def FIR_high_pass(input, cutoff):
    FIR = -cutoff * np.sinc(cutoff * np.arange(-200, 200))
    FIR[int(len(FIR) / 2)] += 1

    FIR_windowed = np.multiply(FIR, get_window('hann', 400))

    w, h = freqz(FIR_windowed, worN=8000)
    return [convolve(FIR_windowed, input), w, h]


# Function that creates a butterworth high-pass filter
def butter_high_pass(input, fs, cutoff):
    b, a = butter(12, cutoff, 'highpass', fs=fs)
    w, h = freqz(b, a)

    return [lfilter(b, a, input), w, h]


# Function that creates a firwin band-pass filter
def firwin_band_pass(input, fs, cutoff):
    cutoff = [cutoff[0] / (fs / 2), cutoff[1] / (fs / 2)]
    filter = firwin(200, cutoff, pass_zero=False)
    w, h = freqz(filter, worN=8000)

    return [convolve(filter, input), w, h]


# Function that creates an FIR band-pass filter
def FIR_band_pass(input, center, width):
    n = np.arange(-1000, 1000)
    FIR_case4 = 2 * np.cos(np.pi * n * center) * width * np.sinc(width * n)
    FIR_windowed = np.multiply(FIR_case4, get_window('hann', 1000 * 2))

    w, h = freqz(FIR_windowed, worN=8000)
    return [convolve(FIR_windowed, input), w, h]


# Function that creates a butterworth band-pass filter
def butter_band_pass(input, fs, cutoff):
    cutoff = [cutoff[0] / (fs / 2), cutoff[1] / (fs / 2)]
    b, a = butter(5, cutoff, btype='band')
    w, h = freqz(b, a)

    return [lfilter(b, a, input), w, h]
In [ ]:
### Case 1 ###

# Load the sound, play it, and plot it's spectrogram
fs, input_sound = wavfile.read("./data/case1.wav")
input_sound = normalize_signal(input_sound)

sound(input_sound, rate=fs, label='case1.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case1.wav")

# Design a filter that fixes things
### A low-pass filter with a cutoff frequency around 6KHz would be good here as the
### noise present in the recording seems to be the only data above that threshold. I chose
### the exact frequency 5700Hz after a process of trial and error.
# Filter using firwin and filtering the input sound
cutoff = 5700
firwin_sound, w, h = firwin_low_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(firwin_sound, rate=fs, label='case1.wav after filtering with firwin')

plot_freq_response(w,
                   h,
                   fs,
                   cutoff,
                   title="Frequency response of the firwin low-pass filter")

plot_spectrogram(firwin_sound,
                 fs,
                 title="Spectrogram of case1.wav after filtering with firwin")

# Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
cutoff = .35  # I arrived at this cutoff frequency by trial and error
FIR_sound, w, h = FIR_low_pass(input_sound, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(FIR_sound, rate=fs, label='case1.wav after filtering with FIR')
plot_freq_response(w,
                   h,
                   fs,
                   cutoff * fs / 2,
                   title="Frequency response of the FIR low-pass filter")

plot_spectrogram(FIR_sound,
                 fs,
                 title="Spectrogram of case1.wav after filtering with FIR")

# Design an IIR Butterworth filter using scipy.signal's routines
cutoff = 5000  # I arrived at this cutoff frequency & order by trial and error

# Filter the input sound
butterworth_sound, w, h = butter_low_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(butterworth_sound,
      rate=fs,
      label='case1.wav after filtering with IIR Butterworth')

plot_freq_response(
    w,
    h,
    fs,
    cutoff,
    title="Frequency response of the IIR low-pass Butterworth filter")

plot_spectrogram(
    butterworth_sound,
    fs,
    title="Spectrogram of case1.wav after filtering with IIR Butterworth")
case1.wav Your browser does not support the audio element.
case1.wav after filtering with firwin Your browser does not support the audio element.
case1.wav after filtering with FIR Your browser does not support the audio element.
case1.wav after filtering with IIR Butterworth Your browser does not support the audio element.
In [ ]:
### Case 2 ###

# Load the sound, play it, and plot it's spectrogram
fs, input_sound = wavfile.read("./data/case2.wav")
input_sound = normalize_signal(input_sound)

sound(input_sound, rate=fs, label='case2.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case2.wav")

# Design a filter that fixes things
### A band-reject filter with the rejected band being around 2KHz - 2.7Khz would be
### good here as there that is where the telephone's frequencies seem to reside.
### Removing this should lead to a much cleaner audio file of the speech.
# Filter using firwin and filtering the input sound
cutoff = [1800, 2900]
firwin_sound, w, h = firwin_band_reject(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(firwin_sound, rate=fs, label='case2.wav after filtering with firwin')

plot_freq_response(w,
                   h,
                   fs,
                   sum(cutoff) / 2,
                   title="Frequency response of the firwin band-reject filter")

plot_spectrogram(firwin_sound,
                 fs,
                 title="Spectrogram of case2.wav after filtering with firwin")

# Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
width = 800 / fs * 2
center = 2400 / fs * 2
FIR_sound, w, h = FIR_band_reject(input_sound, center, width)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(FIR_sound, rate=fs, label='case2.wav after filtering with FIR')

plot_freq_response(w,
                   h,
                   fs,
                   center * fs / 2,
                   title="Frequency response of the FIR band-reject filter")

plot_spectrogram(FIR_sound,
                 fs,
                 title="Spectrogram of case2.wav after filtering with FIR")

# Design an IIR Butterworth filter using scipy.signal's routines
cutoff = [1600, 3100]
butterworth_sound, w, h = butter_band_reject(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(butterworth_sound,
      rate=fs,
      label='case2.wav after filtering with IIR Butterworth')

plot_freq_response(
    w,
    h,
    fs,
    sum(cutoff) / 2,
    title="Frequency response of the IIR band-reject Butterworth filter")

plot_spectrogram(
    butterworth_sound,
    fs,
    title="Spectrogram of case2.wav after filtering with IIR Butterworth")
case2.wav Your browser does not support the audio element.
case2.wav after filtering with firwin Your browser does not support the audio element.
case2.wav after filtering with FIR Your browser does not support the audio element.
case2.wav after filtering with IIR Butterworth Your browser does not support the audio element.
In [ ]:
### Case 3 ###

# Load the sound, play it, and plot it's spectrogram
fs, input_sound = wavfile.read("./data/case3.wav")
input_sound = normalize_signal(input_sound)

sound(input_sound, rate=fs, label='case3.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case3.wav")

# Design a filter that fixes things
### A high-pass filter with a cutoff frequency around 2KHz would be good here as there
### is a lot of low-frequency muddiness in the recording. Removing this should lead to
### a much cleaner sound of just the birds.
# Filter using firwin and filtering the input sound
cutoff = 2000
firwin_sound, w, h = firwin_high_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(firwin_sound, rate=fs, label='case3.wav after filtering with firwin')

plot_freq_response(w,
                   h,
                   fs,
                   cutoff,
                   title="Frequency response of the firwin high-pass filter")

plot_spectrogram(firwin_sound,
                 fs,
                 title="Spectrogram of case3.wav after filtering with firwin")

# Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
cutoff = .25  # I arrived at this cutoff frequency by trial and error
FIR_sound, w, h = FIR_high_pass(input_sound, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(FIR_sound, rate=fs, label='case3.wav after filtering with FIR')

plot_freq_response(w,
                   h,
                   fs,
                   cutoff * fs / 2,
                   title="Frequency response of the FIR high-pass filter")

plot_spectrogram(FIR_sound,
                 fs,
                 title="Spectrogram of case3.wav after filtering with FIR")

# Design an IIR Butterworth filter using scipy.signal's routines
cutoff = 2000  # I arrived at this cutoff frequency & order by trial and error
# butterworth_order_case3 = 12
# b, a = butter(butterworth_order_case3,
#               cutoff,
#               'highpass',
#               fs=fs)

# Filter the input sound
butterworth_sound, w, h = butter_high_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(butterworth_sound,
      rate=fs,
      label='case3.wav after filtering with IIR Butterworth')

plot_freq_response(
    w,
    h,
    fs,
    cutoff,
    title="Frequency response of the IIR high-pass Butterworth filter")

plot_spectrogram(
    butterworth_sound,
    fs,
    title="Spectrogram of case3.wav after filtering with IIR Butterworth")
case3.wav Your browser does not support the audio element.
case3.wav after filtering with firwin Your browser does not support the audio element.
case3.wav after filtering with FIR Your browser does not support the audio element.
case3.wav after filtering with IIR Butterworth Your browser does not support the audio element.
In [ ]:
### Case 4 ###

# Load the sound, play it, and plot it's spectrogram
fs, input_sound = wavfile.read("./data/case4.wav")
input_sound = normalize_signal(input_sound)

sound(input_sound, rate=fs, label='case4.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case4.wav")

# Design a filter that fixes things
### A band-pass filter with the pass band being from 800Hz - 1000Hz would be
### good here as there that is where the morse code's frequencies seem to reside.
### Keeping only this should lead to a much cleaner recording of the message.
# Filter using firwin and filtering the input sound
cutoff = [800, 1000]
firwin_sound, w, h = firwin_band_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(firwin_sound, rate=fs, label='case4.wav after filtering with firwin')

plot_freq_response(w,
                   h,
                   fs, (800 + 1000) / 2,
                   title="Frequency response of the firwin band-pass filter")

plot_spectrogram(firwin_sound,
                 fs,
                 title="Spectrogram of case4.wav after filtering with firwin")

# Design an FIR filter using the formulas in my slides (i.e. do not use scipy.signal)
width = 160 / fs * 2
center = 800 / fs * 2
FIR_sound, w, h = FIR_band_pass(input_sound, center, width)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(FIR_sound, rate=fs, label='case4.wav after filtering with FIR')

plot_freq_response(w,
                   h,
                   fs,
                   center * fs / 2,
                   title="Frequency response of the FIR band-pass filter")

plot_spectrogram(FIR_sound,
                 fs,
                 title="Spectrogram of case4.wav after filtering with FIR")

# Design an IIR Butterworth filter using scipy.signal's routines
cutoff = [800, 1000]
butterworth_sound, w, h = butter_band_pass(input_sound, fs, cutoff)

# Plot the resulting spectrogram, frequency response, and play the resulting sound
sound(butterworth_sound,
      rate=fs,
      label='case4.wav after filtering with IIR Butterworth')

plot_freq_response(
    w,
    h,
    fs,
    sum(cutoff) / 2,
    title="Frequency response of the IIR band-pass Butterworth filter")

plot_spectrogram(
    butterworth_sound,
    fs,
    title="Spectrogram of case4.wav after filtering with IIR Butterworth")
case4.wav Your browser does not support the audio element.
case4.wav after filtering with firwin Your browser does not support the audio element.
case4.wav after filtering with FIR Your browser does not support the audio element.
case4.wav after filtering with IIR Butterworth Your browser does not support the audio element.

Part 2. Designing a simple equalizer¶

For this part we will design a simple graphic equalizer. We will do so using a more straightforward approach as opposed to a bank of filters as discussed in class.

We want to make an equalizer which contains six bands with center frequencies at 100Hz, 200Hz, 400Hz, 800Hz, 1600Hz and 3200Hz. Your equalizer function will take two inputs, one for the input sound and a 6-element gain vector that will indicate how much to boost or suppress each frequency band. Use the scipy.signal.firwin2 function to design a filter that has the desired characteristics. For various settings of the gain vector, use the scipy.signal.freqz command to plot the response of the filter and verify that it behaves as indicated. Experiment with various filter lengths and see which works best.

Once you figure that out, design a graphic equalizer with as many bands as you like (and arbitrary center frequencies as well), and use it to solve the problems in part 1 again. The only thing that should be different in the EQ for each recording should be the gains for each band. Play the output sounds, and show the spectrograms, see how they compare with your previous solutions.

Optional extra credit (+1pt): Use ipywidgets to make interactive sliders and process an audio stream and play it from the speakers in real-time (either from mic input, or just stream audio from disk).

In [ ]:
plt.rcParams["figure.figsize"] = (8, 3)


# Design an equalizer function
def equalizer(input_sound, gains, fs):
    center_freqs = [100, 200, 400, 700, 1600, 3200]
    nyq = fs / 2

    # initialize frequency and gain arrays start and end points
    gain = [gains[0]]
    for i in range(len(gains)):
        gain.append(gains[i])

    gain.append(gains[-1])

    freq = [0]
    for i in range(len(center_freqs)):
        freq.append(center_freqs[i] / nyq)

    freq.append(1)

    filter = firwin2(127, freq, gain)
    a = np.array([1.0, 0])

    # calc frequency response of filter
    w, h = freqz(filter, a)

    # filter the input sound
    return [convolve(filter, input_sound), w, h]


# Show its response with various gain settings
import random

# Importing a test sound to run the eq on
fs, test = wavfile.read("./data/case4.wav")
test = normalize_signal(test)

gains = [1, 1, .8, 1, 0, .1]
gains = [round(x, 2) for x in gains]
eqd, w, h = equalizer(input_sound, gains, fs)
plot_eq(fs, w, h, title=f"Frequency response of the EQ w. gains={gains}")

gains = random.sample(list(np.arange(0, 2, 0.1)), 6)
gains = [round(x, 2) for x in gains]
eqd, w, h = equalizer(input_sound, gains, fs)
plot_eq(fs, w, h, title=f"Frequency response of the EQ w. gains={gains}")

gains = random.sample(list(np.arange(0, 1, 0.01)), 6)
gains = [round(x, 2) for x in gains]
eqd, w, h = equalizer(input_sound, gains, fs)
plot_eq(fs, w, h, title=f"Frequency response of the EQ w. gains={gains}")

gains = [0, 0, 0, 1, 0, 0]
gains = [round(x, 2) for x in gains]
eqd, w, h = equalizer(input_sound, gains, fs)
plot_eq(fs, w, h, title=f"Frequency response of the EQ w. gains={gains}")
In [ ]:
# Design a graphic equalizer with as many bands as you like (and arbitrary center
# frequencies as well), and use it to solve the problems in part 1 again.
def graphic_equalizer(input_sound, gains, fs):
    # Same as the equalizer function, but with more bands at different frequencies
    center_freqs = [100, 600, 800, 1000, 1800, 3000, 3500, 6000]
    nyq = fs / 2

    # initialize frequency and gain arrays start and end points
    gain = [gains[0]]
    for i in range(len(gains)):
        gain.append(gains[i])

    gain.append(gains[-1])

    freq = [0]
    for i in range(len(center_freqs)):
        freq.append(center_freqs[i] / nyq)

    freq.append(1)

    filter = firwin2(127, freq, gain)
    a = np.array([1.0, 0])

    # calc frequency response of filter
    w, h = freqz(filter, a)

    # filter the input sound
    return [convolve(filter, input_sound), w, h]
In [ ]:
### Case 1 ###
fs, input_sound = wavfile.read("./data/case1.wav")
input_sound = normalize_signal(input_sound)
sound(input_sound, rate=fs, label='case1.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case1.wav")

eqd, w, h = graphic_equalizer(input_sound, [1, 1, 1, 1, 1, 1, 1, 0], fs)
sound(eqd, rate=fs, label="EQ'd case1.wav")

plot_eq(fs, w, h)

plot_spectrogram(eqd, fs, title="Spectrogram of EQ'd case1.wav")
case1.wav Your browser does not support the audio element.
EQ'd case1.wav Your browser does not support the audio element.
In [ ]:
### Case 2 ###
fs, input_sound = wavfile.read("./data/case2.wav")
input_sound = normalize_signal(input_sound)
sound(input_sound, rate=fs, label='case2.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case2.wav")

eqd, w, h = graphic_equalizer(input_sound, [1, 1, 1, 1, 0, 0, 1, 1], fs)
sound(eqd, rate=fs, label="EQ'd case2.wav")

plot_eq(fs, w, h)

plot_spectrogram(eqd, fs, title="Spectrogram of EQ'd case2.wav")
case2.wav Your browser does not support the audio element.
EQ'd case2.wav Your browser does not support the audio element.
In [ ]:
### Case 3 ###
fs, input_sound = wavfile.read("./data/case3.wav")
input_sound = normalize_signal(input_sound)
sound(input_sound, rate=fs, label='case3.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case3.wav")

eqd, w, h = graphic_equalizer(input_sound, [0, 0, 0, 0, 0, 1, 1, 1], fs)
sound(eqd, rate=fs, label="EQ'd case3.wav")

plot_eq(fs, w, h)

plot_spectrogram(eqd, fs, title="Spectrogram of EQ'd case3.wav")
case3.wav Your browser does not support the audio element.
EQ'd case3.wav Your browser does not support the audio element.
In [ ]:
### Case 4 ###
fs, input_sound = wavfile.read("./data/case4.wav")
input_sound = normalize_signal(input_sound)
sound(input_sound, rate=fs, label='case4.wav')
plot_spectrogram(input_sound, fs, title="Spectrogram of case4.wav")

eqd, w, h = graphic_equalizer(input_sound, [0, 0, 1, .4, 0, 0, 0, 0], fs)
sound(eqd, rate=fs, label="EQ'd case4.wav")

plot_eq(fs, w, h)

plot_spectrogram(eqd, fs, title="Spectrogram of EQ'd case4.wav")
case4.wav Your browser does not support the audio element.
EQ'd case4.wav Your browser does not support the audio element.